package com.mrx.java8.stream;

import com.alibaba.fastjson.JSON;
import org.junit.jupiter.api.Test;

import java.util.*;
import java.util.stream.Collectors;

import static com.mrx.java8.stream.Employee.*;

/**
 * @create 2018-12-01 9:04
 * <p>
 * 终止操作
 */
public class StreamApi3 {

    List<Employee> employees = Arrays.asList(
            new Employee("张三", 18, 9999.99,Status.FREE),
            new Employee("李四", 38, 5555.55,Status.BUSY),
            new Employee("王五", 50, 6666.66,Status.VOCATION),
            new Employee("赵六", 16, 3333.33,Status.FREE),
            new Employee("田七", 8, 7777.77,Status.BUSY)
    );

    /**
     * 查找与匹配
     * <p>
     * allMatch -- 检查是否匹配所有元素
     * anyMatch -- 检查是否至少匹配一个元素
     * noneMatch -- 检查是否没有匹配所有元素
     * findFirst -- 返回第一个元素
     * findAny -- 返回当前流中的任意元素
     * count -- 返回流中元素的总个数
     * max -- 返回流中最大值
     * min -- 返回流中最小值
     */
    @Test
    public void test1() {
        // allMatch
        boolean b1 = employees.stream()
                .allMatch(e->e.getStatus().equals(Status.BUSY));
        System.out.println(b1);

        // anyMatch
        boolean b2 = employees.stream()
                .anyMatch(e->e.getStatus().equals(Status.BUSY));
        System.out.println(b2);

        // noneMatch
        boolean b3 = employees.stream()
                .noneMatch(e->e.getStatus().equals(Status.BUSY));
        System.out.println(b3);

        // findFirst
        Optional<Employee> op = employees.stream()
                .sorted(Comparator.comparingDouble(Employee::getSalary).reversed())
                .findFirst();
        System.out.println(op.get());

        // findAny
        Optional<Employee> op2 = employees.parallelStream() //
                .filter(e->e.getStatus().equals(Status.FREE))
                .findAny();
        System.out.println(op2.get());
    }


    /** count */
    @Test
    public void test2(){
       Long count =  employees.stream()
                .count();
        System.out.println(count);
    }

    /** max min */
    @Test
    public void test3(){
        Optional<Employee> op1 = employees.stream()
                .max(Comparator.comparingDouble(Employee::getSalary));
        System.out.println(op1.get());

        Optional<Double> op2 =  employees.stream()
                .map(employee -> employee.getSalary())
                .min(Double::compare);
        System.out.println(op2.get());
    }


    /**
     * 规约 -- 可以将流中的元素反复结合起来，得到一个值
     * reduce(T identity,BinaryOperation)
     * reduce(BinaryOperator)
     */
    @Test
    public void test4(){
        List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);

        Integer sum = list.stream().reduce(0,(x,y)->x+y);
        System.out.println(sum);


        Optional<Double> sum2 =  employees.stream()
                .map(Employee::getSalary)
                .reduce(Double::sum);
        System.out.println(sum2.get());
    }


    /**
     * 收集
     * collect-- 将流转换为其他形式，接收一个Collector接口的实现，用于给Stream中元素做汇总的方法
     */
    @Test
    public void test5(){
        List<String> list = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.toList());
        System.out.println(JSON.toJSONString(list));

        System.out.println("--------------------------");

        Set<String> set = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.toSet());
        System.out.println(JSON.toJSONString(set));

        System.out.println("--------------------------");

        HashSet<String> hashSet = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.toCollection(HashSet::new));
        hashSet.forEach(System.out::println);
    }

    @Test
    public void test6(){
        // 总数
        Long count = employees.stream()
                .collect(Collectors.counting());
        System.out.println(count);

        System.out.println("--------------------------");

        // 平均值
        Double average = employees.stream()
                //.map(Employee::getSalary)
                .collect(Collectors.averagingDouble(Employee::getSalary));
        System.out.println(average);

        System.out.println("--------------------------");

        // 总和
        Double sum = employees.stream()
                .collect(Collectors.summingDouble(Employee::getSalary));
        System.out.println(sum);

        System.out.println("--------------------------");

        // 最大值
        Optional<Employee> op1 = employees.stream()
                .collect(Collectors.maxBy(Comparator.comparingDouble(Employee::getSalary)));
        System.out.println(op1.get());

        System.out.println("--------------------------");

        // 最小值
        Optional<Double> op2 = employees.stream()
                .map(Employee::getSalary)
                .collect(Collectors.minBy(Double::compare));
        System.out.println(op2.get());

    }


    /** 分组 */
    @Test
    public void test7(){
        Map<Status,List<Employee>> map = employees.stream()
                .collect(Collectors.groupingBy(Employee::getStatus));
        System.out.println(map);
    }

    /** 多级分组*/
    @Test
    public void test8(){
        Map<Status,Map<String,List<Employee>>> map = employees.stream()
                .collect(Collectors.groupingBy(Employee::getStatus,Collectors.groupingBy(e->{
                    if(e.getAge()<=35){
                        return "青年";
                    }else if(e.getAge()<=50){
                        return "中年";
                    }else {
                        return "老年";
                    }
                })));
        System.out.println(map);
    }

    /** 分区 */
    @Test
    public void test9(){
        Map<Boolean,List<Employee>> map = employees.stream()
                .collect(Collectors.partitioningBy(e->e.getSalary()>8000));
        System.out.println(map);
    }


    /** 统计 */
    @Test
    public void test10(){
        DoubleSummaryStatistics dss =  employees.stream()
                .collect(Collectors.summarizingDouble(Employee::getSalary));
        System.out.println(dss.getSum());
        System.out.println(dss.getAverage());
        System.out.println(dss.getMax());
        System.out.println(dss.getMin());
    }

    /** 连接字符串 */
    @Test
    public void test11(){
        String str = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.joining(",")); //joining(delimiter, "", "");
        System.out.println(str);
    }




}
